// one 64+64 or two 32+32 or four 16+16 or eight 8+8 

module add_mix(/*AUTOARG*/
   // Outputs
   o_sum, o_carrys,
   // Inputs
   i_a, i_b, i_mode
   );
   output logic [63:0] o_sum;
   output logic [7:0]  o_carrys;
   input logic [63:0]  i_a, i_b;	// the addend
   input logic [3:0]   i_mode;		// i_mode[3..0] => 64/32/16/8 mode

   logic 			   mode8, mode16, mode32, mode64;
   assign {mode64, mode32, mode16, mode8} = i_mode;
   
   logic [63:0] 	   op_a, op_b;
   // dig the MSB of each mode as a hole
   assign op_a = { i_a[63] & ~(mode8 | mode16 | mode32 | mode64), i_a[62:56], 
				   i_a[55] & ~(mode8), i_a[54:48], 
				   i_a[47] & ~(mode8 | mode16), i_a[46:40], 
				   i_a[39] & ~(mode8), i_a[38:32], 
				   i_a[31] & ~(mode8 | mode16 | mode32), i_a[30:24], 
				   i_a[23] & ~(mode8), i_a[22:16], 
				   i_a[15] & ~(mode8 | mode16), i_a[14:8], 
				   i_a[7]  & ~(mode8), i_a[6:0] };

   assign op_b = { i_b[63] & ~(mode8 | mode16 | mode32 | mode64), i_b[62:56], 
				   i_b[55] & ~(mode8), i_b[54:48], 
				   i_b[47] & ~(mode8 | mode16), i_b[46:40], 
				   i_b[39] & ~(mode8), i_b[38:32], 
				   i_b[31] & ~(mode8 | mode16 | mode32), i_b[30:24], 
				   i_b[23] & ~(mode8), i_b[22:16], 
				   i_b[15] & ~(mode8 | mode16), i_b[14:8], 
				   i_b[7]  & ~(mode8), i_b[6:0] };

   logic [63:0] sum_with_holes;
   // assign sum_with_holes = op_a + op_b;
   DW01_add #(.width(64)) U_add(
   								.A(op_a),
   								.B(op_b),
   								.CI(1'b0),
   								.SUM(sum_with_holes),
   								.CO() ); // infact, this Carry is for all mode
   
   
   logic [7:0] 	holes, carrys;
   generate
	  genvar 	i;
	  for(i=0;i<8;i++)
		begin : gen_holes_carrys
		   DW01_add #(.width(1)) U_holes_add(
   											 .A(i_a[i*8+7]), // 7,15,...,63
   											 .B(i_b[i*8+7]),
   											 .CI(sum_with_holes[i*8+7]),
   											 .SUM(holes[i]),
   											 .CO(carrys[i]) );
		end
   endgenerate

   assign o_sum = { (mode8 | mode16 | mode32 | mode64) ? holes[7] : sum_with_holes[63], sum_with_holes[62:56],
					(mode8) ? holes[6] : sum_with_holes[55], sum_with_holes[54:48],
					(mode8 | mode16) ? holes[5] : sum_with_holes[47], sum_with_holes[46:40],
					(mode8) ? holes[4] : sum_with_holes[39], sum_with_holes[38:32],
					(mode8 | mode16 | mode32) ? holes[3] : sum_with_holes[31], sum_with_holes[30:24],
					(mode8) ? holes[2] : sum_with_holes[23], sum_with_holes[22:16],
					(mode8 | mode16) ? holes[1] : sum_with_holes[15], sum_with_holes[14:8],
					(mode8) ? holes[0] : sum_with_holes[7], sum_with_holes[6:0] };
   assign o_carrys = carrys;
   
endmodule // add_mix


